package com.ffcs.crmd.tsp.api.dto.job;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.ffcs.crmd.tsp.api.dto.task.TspJobDataMap;
import com.ffcs.crmd.tsp.api.dto.task.TspJobInstance;
import com.ffcs.crmd.tsp.api.task.job.IJobExecutionContext;
import com.ffcs.crmd.tsp.common.constant.TspAppConstant;
import com.ffcs.crmd.tsp.common.exception.TspException;
import com.thoughtworks.xstream.annotations.XStreamAliasType;

/**
 * 
 * 功能说明:任务执行上下文
 *
 * @author ZHONGFUHUA
 * 
 * @since 1.0.0-SNAPSHOT
 *
 */
@XStreamAliasType("TspJobExecutionContext")
public class TspJobExecutionContext<T> implements IJobExecutionContext<T>, Serializable {
    
    /**
     * 
     */
    private static final long serialVersionUID  = 2040559515807228101L;
    
    private List<T>           bussinessDataList = new ArrayList<T>();
    
    private TspJobDataMap     tspJobDataMap;
    
    private TspJobInstance    tspJobInstance;
    
    private String            fireInstanceId;
    
    private String            schedulerName;
    
    private Date              fireTime;
    
    private Date              scheduledFireTime;
    
    private Date              previousFireTime;
    
    private Date              nextFireTime;
    
    private long              jobRunTime;
    
    private boolean           recovering;
    
    private int               refireCount;
    
    
    public TspJobInstance getTspJobInstance() {
        return tspJobInstance;
    }
    
    public void setTspJobInstance(TspJobInstance tspJobDetail) {
        this.tspJobInstance = tspJobDetail;
    }
    
    public Date getFireTime() {
        return fireTime;
    }
    
    public void setFireTime(Date fireTime) {
        this.fireTime = fireTime;
    }
    
    public Date getScheduledFireTime() {
        return scheduledFireTime;
    }
    
    public void setScheduledFireTime(Date scheduledFireTime) {
        this.scheduledFireTime = scheduledFireTime;
    }
    
    public Date getPreviousFireTime() {
        return previousFireTime;
    }
    
    public void setPreviousFireTime(Date previousFireTime) {
        this.previousFireTime = previousFireTime;
    }
    
    public Date getNextFireTime() {
        return nextFireTime;
    }
    
    public void setNextFireTime(Date nextFireTime) {
        this.nextFireTime = nextFireTime;
    }
    
    public String getFireInstanceId() {
        return fireInstanceId;
    }
    
    public void setFireInstanceId(String fireInstanceId) {
        this.fireInstanceId = fireInstanceId;
    }
    
    /**
     * 功能说明: 获取schedulerName
     *
     * @return schedulerName schedulerName
     */
    @Override
    public String getSchedulerName() {
        return schedulerName;
    }
    
    /**
     * 功能说明: 设置schedulerName
     *
     * @param schedulerName schedulerName 
     */
    public void setSchedulerName(String schedulerName) {
        this.schedulerName = schedulerName;
    }
    
    public long getJobRunTime() {
        return jobRunTime;
    }
    
    public void setJobRunTime(long jobRunTime) {
        this.jobRunTime = jobRunTime;
    }
    
    public boolean isRecovering() {
        return recovering;
    }
    
    public void setRecovering(boolean recovering) {
        this.recovering = recovering;
    }
    
    public int getRefireCount() {
        return refireCount;
    }
    
    public void incrementRefireCount() {
        this.refireCount++;
    }
    
    
    @Override
    public void joinBussinessData(T data) {
        this.bussinessDataList.add(data);
    }
    
    @Override
    public void joinBussinessDatas(List<T> datas) {
        this.bussinessDataList.addAll(datas);
    }
    
    @Override
    public void removeBussinessData(T data) {
        this.bussinessDataList.remove(data);
    }
    
    @Override
    public void removeAllBussinessData() {
        this.bussinessDataList.clear();
    }
    
    @Override
    public List<T> getBussinessDatas() {
        return bussinessDataList;
    }
    @Override
    public TspJobDataMap getTspJobDataMap() {
        return tspJobDataMap;
    }
    
    public void setTspJobDataMap(TspJobDataMap tspJobDataMap) {
        this.tspJobDataMap = tspJobDataMap;
    }
    
    @Override
    public String getHintSQLByDataNodes(String sql) throws TspException {
        if (StringUtils.isBlank(sql)) {
            new TspException("The <code>sql</code> String is not null or empty");
        }
        String[] slices = getSlices();
        if (slices != null && slices.length > 0) {
            Map<String, String[]> hintDatas = new HashMap<String, String[]>();
            hintDatas.put("dn", slices);
            String result = "/* !HINT(%s)*/ %s".replaceFirst("%s", JSON.toJSONString(hintDatas));
            result = result.replaceFirst("%s", sql);
            return result;
        } else {
            return sql;
        }
    }
    
    @Override
    public String[] getSlices() {
        String slices = tspJobDataMap.getStringFromString(TspAppConstant.TSP_PARAM_SLICES);
        if (StringUtils.isNoneBlank(slices)) {
            return slices.split(",");
        }
        return null;
    }
    
    @Override
    public String getSliceGroupName() {
        return tspJobDataMap.getStringFromString(TspAppConstant.TSP_PARAM_SLICES_GROUP);
    }
    
    
    @Override
    public String toString() {
        return "TspJobExecutionContext [tspJobDetail=" + tspJobInstance + ", fireTime=" + fireTime + ", scheduledFireTime=" + scheduledFireTime
            + ", previousFireTime=" + previousFireTime + ", nextFireTime=" + nextFireTime + ", fireInstanceId=" + fireInstanceId + ", jobRunTime="
            + jobRunTime + ", recovering=" + recovering + ", refireCount=" + refireCount + "]";
    }
}
